package com.plat.sdk.common;

/**
 * @author Created by ydong on 2020/1/20 15:37
 * @desc:
 */

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

import java.util.List;

/**
 * 延迟加载： Viewpager 内部嵌套了很多Fragment时，{@link androidx.viewpager.widget.ViewPager#setOffscreenPageLimit(int limit)}默认会创建当前Fragment前后的limit 个Fragment,但是
 * 如果每个Fragment创建是内部数据也同步加载，会导致卡顿性能问题，所以有一部分Fragment虽然创建了但是数据并不需要立即加载，只有在由不可见到可见时才需要加载。
 * <p>
 * 延迟加载只有重写了{@link LazyFragment#onVisible(boolean mIsFirstVisible)}这个方法,在这个方法里面加载数据才有用
 *
 * @Override public void onVisible(boolean isFirstVisible) {
 * super.onVisible(isFirstVisible);
 * if (isFirstVisible) {
 * loadData();
 * }
 * }
 * </p>
 */
public abstract class LazyFragment extends Fragment {

    private boolean mViewCreated = false;
    private boolean mIsFirstVisible = true;
    private boolean mUserVisible = false;
    private View mRootView = null;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (mRootView == null) {
            final int layoutId = getLayoutRes();
            if (layoutId > 0) {
                mRootView = inflater.inflate(getLayoutRes(), container, false);
            }
        }
        mViewCreated = true;
        return mRootView;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("ydong", this.getClass().getSimpleName() + "\tonCreate");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d("ydong", this.getClass().getSimpleName() + "\tonResume");
        if (!mIsFirstVisible) {
            if (!isHidden() && !mUserVisible && getUserVisibleHint()) {
                dispatchUserVisibleHint(true);
            }
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        if (mUserVisible && getUserVisibleHint()) {
            dispatchUserVisibleHint(false);
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mRootView = null;
        mViewCreated = false;
        mIsFirstVisible = true;
    }


    @Nullable
    public View getRootView() {
        return mRootView;
    }

    /**
     * 这里对findViewById包装一下，在字fragment中就可以不用mRootView.findViewById来获取View了，简洁很多
     */
    public final <V extends View> V findViewById(@IdRes int id) {
        if (mRootView == null) {
            return null;
        }
        return mRootView.findViewById(id);
    }


    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (mViewCreated) {
            if (isVisibleToUser && !mUserVisible) {
                dispatchUserVisibleHint(true);
            } else if (!isVisibleToUser && mUserVisible) {
                dispatchUserVisibleHint(false);
            }
        }
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (!isHidden() && getUserVisibleHint()) {
            dispatchUserVisibleHint(true);
        }
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        if (hidden) {
            dispatchUserVisibleHint(false);
        } else {
            dispatchUserVisibleHint(true);
        }
    }

    private void dispatchUserVisibleHint(boolean visible) {
        if (visible && isParentInvisible()) return;
        if (mUserVisible == visible) {
            return;
        }
        mUserVisible = visible;
        if (visible) {
            if (mIsFirstVisible) {
                mIsFirstVisible = false;
                onVisible(true);
            } else {
                onVisible(false);
            }
            dispatchChildVisibleState(true);
        } else {
            dispatchChildVisibleState(false);
            onInvisible();
        }
    }

    private boolean isParentInvisible() {
        LazyFragment fragment = (LazyFragment) getParentFragment();
        return fragment != null && !fragment.isSupportUserVisible();
    }

    private boolean isSupportUserVisible() {
        return mUserVisible;
    }

    private void dispatchChildVisibleState(boolean visible) {
        FragmentManager childFragmentManager = getChildFragmentManager();
        List<Fragment> fragments = childFragmentManager.getFragments();
        if (!fragments.isEmpty()) {
            for (Fragment child : fragments) {
                if (child instanceof LazyFragment && !child.isHidden() && child.getUserVisibleHint()) {
                    ((LazyFragment) child).dispatchUserVisibleHint(visible);
                }
            }
        }
    }

    /**
     * 界面由不可见到可见，fragment实现该方法，判断下如果isFirstVisible is true,则执行加载数据
     *
     * @param isFirstVisible 是否是第一次加载数据 true 是 false 不是
     */
    public void onVisible(boolean isFirstVisible) {
        // TODO: 2020/1/20 在这里面加载数据
    }

    /**
     * 可以在这个实现类里取消后台线程的加载数据操作
     */
    public void onInvisible() {
    }

    /**
     * 子Fragment继承自该类实现该方法
     * 获取布局资源文件
     *
     * @return layoutId
     */
    protected abstract int getLayoutRes();
}

